package com.peng.safety.utils

import android.os.Handler
import android.os.Looper
import androidx.appcompat.app.AlertDialog
import androidx.biometric.BiometricPrompt
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity

/**
 * Google生物识别（指纹，高版本有人脸）
 * @author pengc
 */
object SafetyCheck {

    private val handler = Handler(Looper.getMainLooper())

    private val bioInfo = BiometricPrompt.PromptInfo.Builder()
        .setTitle("身份验证")
        .setSubtitle("本程序需要验证您的身份")
        .setNegativeButtonText("取消")
        .build()

    @JvmStatic
    fun checkFingerPrint(context: Fragment, callback: SafeCheckResultCallback) {
        val authCallback = object : BiometricPrompt.AuthenticationCallback() {
            override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
                callback.checkComplete(true)
            }

            override fun onAuthenticationFailed() {
                callback.checkComplete(false)
            }

            override fun onAuthenticationError(errorCode: Int, errorString: CharSequence) {
                if (!callback.checkError(errorCode, errorString.toString())) {
                    context.activity?.let {
                        AlertDialog.Builder(it)
                            .setTitle("提示")
                            .setMessage("身份验证错误：$errorString   code = $errorCode")
                            .setPositiveButton("确定", null)
                            .create().show()
                    }
                }
            }
        }
        BiometricPrompt(context, { command -> handler.post(command) }, authCallback).authenticate(
            bioInfo
        )
    }

    @JvmStatic
    fun checkFingerPrint(context: FragmentActivity, callback: SafeCheckResultCallback) {

        val authCallback = object : BiometricPrompt.AuthenticationCallback() {
            override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
                callback.checkComplete(true)
            }

            override fun onAuthenticationFailed() {
                callback.checkComplete(false)
            }

            override fun onAuthenticationError(errorCode: Int, errorString: CharSequence) {
                if (!callback.checkError(errorCode, errorString.toString())) {
                    AlertDialog.Builder(context)
                        .setTitle("提示")
                        .setMessage("身份验证错误：$errorString   code = $errorCode")
                        .setPositiveButton("确定", null)
                        .create().show()
                }
            }
        }
        BiometricPrompt(context, { command -> handler.post(command) }, authCallback).authenticate(
            bioInfo
        )
    }

}

/**
 * 身份验证结果的callback
 */
abstract class SafeCheckResultCallback {
    /**
     * 身份验证结束
     * @param success 是否验证通过
     */
    open fun checkComplete(success: Boolean) {}

    /**
     * 身份验证失败
     * @param errCode 错误码
     * @param errMsg  错误信息
     * @return 是否子类处理，false的话，此类处理，弹框提示
     */
    open fun checkError(errCode: Int, errMsg: String): Boolean = false
}


/**
 * DSL方式调用，正在学习中
 */
class SafeCheckDsl {

    internal var complete: ((Boolean) -> Unit)? = null
    internal var error: ((String) -> Boolean)? = null

    infix fun checkComplete(checkComplete: ((Boolean) -> Unit)?) {
        this.complete = checkComplete
    }

    infix fun checkError(checkError: ((msg: String) -> Boolean)?) {
        this.error = checkError
    }

    fun startWithActivity(activity: FragmentActivity) {
        SafetyCheck.checkFingerPrint(activity, object : SafeCheckResultCallback() {
            override fun checkComplete(success: Boolean) {
                complete?.invoke(success)
            }

            override fun checkError(errCode: Int, errMsg: String): Boolean {
                return error?.invoke(errMsg) ?: false
            }
        })
    }

    fun startWithFragment(fragment: Fragment) {
        SafetyCheck.checkFingerPrint(fragment, object : SafeCheckResultCallback() {
            override fun checkComplete(success: Boolean) {
                complete?.invoke(success)
            }

            override fun checkError(errCode: Int, errMsg: String): Boolean {
                return error?.invoke(errMsg) ?: false
            }
        })
    }
}

fun FragmentActivity.checkFinger(safeDsl: SafeCheckDsl.() -> Unit) {
    SafeCheckDsl().apply(safeDsl).startWithActivity(this)
}

fun Fragment.checkFinger(safeDsl: SafeCheckDsl.() -> Unit) {
    SafeCheckDsl().apply(safeDsl).startWithFragment(this)
}